<!DOCTYPE html>
<html lang="en" data-theme="black">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>产品中心页</title>
  <link rel="stylesheet" href="./fonts/index.css">
  <style>
    * {
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }

    html,
    body {
      width: 100%;
      height: 100%;
    }

    .container {
      position: relative;
      display: flex;
      width: 100%;
      height: 100%;
      color: #fff;
      padding-right: 2px;
      flex-direction: column;
      font-family: Microsoft YaHei-Bold, Microsoft YaHei;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    }

    [data-theme='black'] .container {
      color: #fff;
      /* background: #2d2e35; */
    }

    [data-theme='white'] .container {
      color: #000;
      background: #fff;
    }

    .product-wrap {
      flex: 1;
      padding: 20px;
    }

    .xz-scroll {
      overflow: hidden auto;
    }

    .xz-scroll::-webkit-scrollbar {
      width: 4px;
      height: 4px;
    }

    .xz-scroll:hover::-webkit-scrollbar-thumb {
      background-color: rgba(255, 255, 255, 0.2);
    }

    [data-theme='white'] .xz-scroll:hover::-webkit-scrollbar-thumb {
      background-color: rgba(0, 0, 0, 0.1);
    }

    .xz-scroll::-webkit-scrollbar-thumb {
      border-radius: 21px;
      background-color: transparent;
    }

    .xz-scroll::-webkit-scrollbar-thumb:hover {
      background-color: rgba(255, 255, 255, 0.3);
    }

    [data-theme='white'] .xz-scroll::-webkit-scrollbar-thumb:hover {
      background-color: rgba(0, 0, 0, 0.2);
    }

    .svg-icon {
      width: 1em;
      height: 1em;
      fill: currentColor;
      overflow: hidden;
    }

    .product-wrap .product {
      display: flex;
      height: 138px;
      padding: 30px 18px 30px 20px;
      align-items: center;
      border-radius: 10px;
      margin-bottom: 14px;
      background-color: rgba(255, 255, 255, 0.03);
    }

    [data-theme='white'] .product-wrap .product {
      background-color: rgba(0, 0, 0, 0.03);
    }

    .product-wrap .product:hover {
      background-color: rgba(255, 255, 255, 0.08);
    }

    [data-theme='white'] .product-wrap .product:hover {
      background-color: rgba(0, 0, 0, 0.08);
    }

    .product-wrap .product:last-of-type {
      margin-bottom: 0;
    }

    .product .left {
      flex: 86px 0 0;
      display: flex;
      font-size: 12px;
      align-items: center;
      flex-direction: column;
    }

    .product .left .logo {
      width: 48px;
      height: 48px;
      margin-bottom: 10px;
    }

    .product .left .name {
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .line {
      width: 1px;
      height: 100%;
      opacity: 0.1;
      margin: 0 30px 0 22px;
      background-color: #fff;
    }

    [data-theme='white'] .line {
      background-color: #000;
    }

    .features {
      flex: 1;
      margin-right: 20px;
      min-width: 100px;
    }

    .features .feature {
      font-size: 12px;
      text-overflow: ellipsis;
      overflow: hidden;
      white-space: nowrap;
      padding: 2px 0;
      margin-bottom: 8px;
    }

    .features .feature:last-of-type {
      margin-bottom: 0;
    }

    .features .feature .desc {
      opacity: 0.7;
      margin-left: 12px;
    }

    .right {
      flex: 92px 0 0;
    }

    .right .btn+.btn {
      margin-top: 12px;
    }

    .btn {
      display: flex;
      cursor: pointer;
      height: 30px;
      justify-content: center;
      align-items: center;
      font-size: 12px;
      border-radius: 4px;
      user-select: none;
    }

    .btn .svg-icon {
      margin-right: 4px;
    }

    .download {
      position: relative;
      color: #fff;
      background: #237855;
    }

    [data-theme='white'] .download {
      background-color: #1FC880;
    }

    .download.disabled {
      cursor: not-allowed;
    }

    .download.disabled:hover {
      background-color: #237855;
    }

    [data-theme='white'] .download.disabled:hover {
      background-color: #1FC880;
    }

    .download:hover {
      background-color: #1FC880;
    }

    [data-theme='white'] .download:hover {
      background-color: #12915B;
    }

    .download .watting {
      display: none;
    }

    .download.watting .normal {
      display: none;
    }

    .download.watting .watting {
      display: inline-block;
    }

    .progress-wrap {
      position: absolute;
      left: 0;
      right: 0;
      bottom: 0;
      height: 3px;
    }

    .progress {
      height: 100%;
      background: #1FC880;
      border-radius: 4px;
    }

    [data-theme='white'] .progress {
      background: #12915B;
    }

    .web {
      color: #1FC880;
      line-height: 28px;
      border: 1px solid rgba(31, 200, 128, 0.4);
    }

    [data-theme='white'] .web {
      border-color: #1FC880;
    }

    .web:hover {
      border-color: #1FC880;
    }

    [data-theme='white'] .web:hover {
      border-color: #12915B;
    }

    .no-data {
      opacity: .7;
      text-align: center;
      font-size: 18px;
      line-height: 60px;
    }

    .page-loading-layer {
      position: fixed;
      display: flex;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 999;
      align-items: center;
      flex-direction: column;
      justify-content: center;
      color: rgba(255, 255, 255, 0.7);
      background-color: #2d2e35;
    }

    [data-theme='white'] .page-loading-layer {
      color: rgba(0, 0, 0, 0.7);
      background-color: #fff;
    }

    .page-loading-layer .loading-img {
      width: 90px;
      height: 90px;
      background: url('./loading-blank.png') no-repeat center/100% 100%;
    }

    [data-theme='white'] .page-loading-layer .loading-img {
      background-image: url('./loading-white.png');
    }

    .page-loading-layer .loading-text {
      white-space: nowrap;
    }
  </style>
</head>

<body>
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
    style="position: absolute; width: 0; height: 0" aria-hidden="true" id="__SVG_SPRITE_NODE__">
    <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" fill="none" id="icon-web">
      <g id="icon-web_f">
        <rect id="icon-web_Rectangle 126" x="1.5" y="1.5" width="11" height="8" rx="1.5" stroke="currentColor"></rect>
        <path id="icon-web_Vector 14" d="M4 12.5H10" stroke="currentColor" stroke-linecap="round"></path>
      </g>
    </symbol>
    <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" fill="none" id="icon-download">
      <g id="icon-download_f">
        <g id="icon-download_Group 292">
          <path id="icon-download_Vector 13" d="M7 1V12" stroke="currentColor" stroke-linecap="round"
            stroke-linejoin="round">
          </path>
          <path id="icon-download_Vector 12" d="M2 7.5L6.94975 12.4497L11.8995 7.5" stroke="currentColor"
            stroke-linecap="round" stroke-linejoin="round"></path>
        </g>
      </g>
    </symbol>

  </svg>
  <div class="container">
    <ul id="products" class="product-wrap  xz-scroll"> </ul>
    <div id="page-loading-layer" class="page-loading-layer">
      <div class="loading-img"></div>
      <div class="loading-text">页面加载中，请稍后……</div>
    </div>
  </div>
</body>
<script>
  // 测试环境
  // const prefixUrl = 'http://10.10.30.40:8650'
  // 正式环境
  const prefixUrl = 'https://cfg-xzapi.cqttech.com'

  // 点击事件
  const czc = window._czc || []
  // 阻止右键
  document.body.addEventListener(
    'contextmenu',
    e => {
      e.preventDefault()
    },
    false
  )
  // 注册客户端通知
  function registerInformApi(apiName, cb) {
    ; (window.xz_register && window.xz_register(apiName, cb)) ||
      (window[apiName] = cb)
  }
  // 调用客户端接口
  function invokeAsyncAPi() {
    var a = Array.prototype.slice.call(arguments)
    return new Promise(resolve => {
      a.push((...args) => resolve(args.length > 1 ? args : args[0]))
      window.xz_call && window.xz_call.apply(this, a)
    })
  }
  function invokeAPi() {
    var a = Array.prototype.slice.call(arguments)
    return window.xz_call && window.xz_call.apply(this, a)
  }

  invokeAPi('IsDesktopApp', res => {
    var box = document.createElement('div')
    box.style.display = 'none'
    var script = document.createElement('script')
    script.type = 'text/javascript'
    var id = res ? 1278205658 : 1281148169
    script.src = 'https://s9.cnzz.com/z_stat.php?id=' + id + '&web_id=' + id
    box.append(script)
    document.body.append(box)
  })

  // 皮肤设置
  function handlerSwitchSkin(Skin) {
    const skin = {
      0: 'black',
      1: 'white'
    }
    const theme = skin[Skin || 0]
    document.documentElement.setAttribute('data-theme', theme)
  }

  // 皮肤通知
  registerInformApi('Notify_SwitchSkin', ({ Skin }) => {
    handlerSwitchSkin(Skin)
  })
  // 显示通知
  registerInformApi('Notify_Refresh', () => {
    getList()
  })

  function debounce(func, wait = 200, immediate) {
    let timeout, args, context, timestamp, result

    const later = function () {
      // 据上一次触发时间间隔
      const last = +new Date() - timestamp

      // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
      if (last < wait && last > 0) {
        timeout = setTimeout(later, wait - last)
      } else {
        timeout = null
        // 如果设定为immediate===true，因为开始边界已经调用过了此处无需调用
        if (!immediate) {
          result = func.apply(context, args)
          if (!timeout) context = args = null
        }
      }
    }

    return function (...args) {
      context = this
      timestamp = +new Date()
      const callNow = immediate && !timeout
      // 如果延时不存在，重新设定延时
      if (!timeout) timeout = setTimeout(later, wait)
      if (callNow) {
        result = func.apply(context, args)
        context = args = null
      }

      return result
    }
  }
  // 阻止频繁触发
  let productList = []
  let productMap = {}
  let curIndex = 0
  // 等待列表
  let wattings = []
  const getList = debounce(function () {
    ajax({
      url: prefixUrl + '/api/v1/cs/configdata',
      data: {
        app_id: 108,
        keyname: 'cpzx',
        version: '3.0.5.10',
        union_id: 0
      },
      success(res) {
        res = JSON.parse(res || '{}')
        hideLoadLayer()
        productList = (res.params || []).sort((a, b) => a.order - b.order)
        const htmlStr = productList.reduce((str, item, index) => {
          str += `
                  <li class="product">
                    <div class="left">
                      <img src="${item.logo}" alt=""
                        class="logo">
                      <div class="name">${item.name}</div>
                    </div>
                    <div class="line"></div>
                    <div class="features">
                  `
          str += item.features.reduce((s, it) => {

            s += `
                  <div class="feature" title="${it.title}：${it.desc}">
                    <span class="title">${it.title}</span>
                    <span class="desc">${it.desc}</span>
                  </div>
                  `
            return s
          }, '')
          str += `
                  </div>
                  <div class="right" data-index="${index}">
                    <div class="btn download ${wattings.includes(item.downUrl) ? 'disabled watting' : ''}" onclick="downHandler(this)">
                      <svg xmlns="http://www.w3.org/2000/svg" class="svg-icon">
                        <use xlink:href="#icon-download"></use>
                      </svg>
                      <span class="text normal">下载</span>
                      <span class="text watting">等待中...</span>
                      <div class="progress-wrap">
                        <div class="progress" style="width:0%;"></div>
                      </div>
                    </div>
                  `
          if (item.webUrl) str += `
                            <div class="btn web" onclick="goWeb(this)">
                              <svg xmlns="http://www.w3.org/2000/svg" class="svg-icon">
                                <use xlink:href="#icon-web"></use>
                              </svg>
                              <span>官网</span>
                            </div>
                          `
          str += '</div></li>'
          return str
        }, '')
        document.getElementById('products').innerHTML = htmlStr
        productMap = productList.reduce((obj, t, index) => {
          obj[t.downUrl] = {
            index,
            ...t
          }
          return obj
        }, {})
      },
      fail() {
        hideLoadLayer()
      }
    })
  }, 500, true)

  getList()
  function hideLoadLayer() {
    const dom = document.getElementById('page-loading-layer')
    dom && (dom.style.display = 'none')
  }
  function downHandler(that) {
    if (that.classList.contains('disabled')) return
    that.classList.add('disabled')
    that.classList.add('watting')
    const index = curIndex = that.parentNode.dataset.index
    const product = productList[index]
    invokeAsyncAPi('DownLoadProduct', product.downUrl, product.name)
    invokeAPi('HtmlClickReport', { ReportID: 25413 })
    wattings.push(product.downUrl)
  }

  // 下载进度
  let timerId = null
  registerInformApi('Notify_DownlaodProgress', function (int, link) {
    const index = productMap[link]?.index
    const dom = document.querySelector(`[data-index="${index}"]`)
    if (dom) {
      const downDom = dom.querySelector('.download')
      const classList = downDom.classList
      classList.contains('watting') && classList.remove('watting')
      // !classList.contains('loading') && classList.add('loading')
      const progressDom = dom.querySelector('.progress')
      progressDom.style.width = int + '%'
      if (int === 100) {
        if (timerId) {
          clearTimeout(timerId)
          timerId = null
        }
        timerId = setTimeout(() => {
          progressDom.style.width = 0 + '%'
          classList.contains('disabled') && classList.remove('disabled')
          // classList.contains('loading') && classList.remove('loading')
        }, 200)
        wattings = wattings.filter(l => l !== link)
      } else {
        !classList.contains('disabled') && classList.add('disabled')
      }
    }
  })

  // 取消选择下载目录
  registerInformApi('Notify_Cancel', function () {
    const dom = document.querySelector(`[data-index="${curIndex}"]`)
    if (dom) {
      const classList = dom.querySelector('.download').classList
      classList.contains('watting') && classList.remove('watting')
      classList.contains('disabled') && classList.remove('disabled')
      const product = productList[curIndex]
      product && (wattings = wattings.filter(l => l !== product.downUrl))
    }
  })
  // 官网
  function goWeb(that) {
    const index = that.parentNode.dataset.index
    const product = productList[index]
    invokeAsyncAPi('OpenUrl', product.webUrl)
    invokeAPi('HtmlClickReport', { ReportID: 25415 })
  }

  // 重新下载
  registerInformApi('Notify_ReDownlaod', function (link) {
    const index = productMap[link]?.index
    const dom = document.querySelector(`[data-index="${index}"]`)
    if (dom) {
      const downDom = dom.querySelector('.download')
      const classList = downDom.classList
      classList.add('watting')
      classList.add('disabled')
      const progressDom = dom.querySelector('.progress')
      progressDom.style.width = '0%'
      wattings.push(link)
    }
  })
  /*
       request 网络请求
     */
  function ajax(options) {
    /**
     * 传入方式默认为对象
     * */
    options = options || {}
    /**
     * 默认为GET请求
     * */
    options.type = (options.type || 'GET').toUpperCase()
    /**
     * 返回值类型默认为json
     * */
    options.dataType = options.dataType || 'json'
    /**
     * 默认为异步请求
     * */
    options.async = options.async || true
    options.contentType = options.contentType || 'application/json;charset:utf-8;'
    /**
     * 对需要传入的参数的处理
     * */
    var params = getParams(options.data)
    var xhr
    /**
     * 创建一个 ajax请求
     * W3C标准和IE标准
     */
    if (window.XMLHttpRequest) {
      /**
       * W3C标准
       * */
      xhr = new XMLHttpRequest()
    } else {
      /**
       * IE标准
       * @type {ActiveXObject}
       */
      xhr = new ActiveXObject('Microsoft.XMLHTTP')
    }
    xhr.onreadystatechange = function () {
      if (xhr.readyState == 4) {
        var status = xhr.status
        if (status >= 200 && status < 300) {
          options.success &&
            options.success(xhr.responseText, xhr.responseXML)
        } else {
          options.fail && options.fail(status)
        }
        options.finally && options.finally()
      }
    }
    if (options.type == 'GET') {
      xhr.open('GET', options.url + '?' + params, options.async)
      xhr.send(null)
    } else if (options.type == 'POST') {
      /**
       *打开请求
       * */
      xhr.open('POST', options.url, options.async)
      /**
       * POST请求设置请求头
       * */
      xhr.setRequestHeader(
        'Content-Type',
        options.contentType
      )
      /**
       * 发送请求参数
       */
      xhr.send(options.contentType.includes('application/json') ? JSON.stringify(options.data) : params)
    }
  }
  /**
   * 对象参数的处理
   * @param data
   * @returns {string}
   */
  function getParams(data) {
    var arr = []
    for (var param in data) {
      arr.push(
        encodeURIComponent(param) + '=' + encodeURIComponent(data[param])
      )
    }
    return arr.join('&')
  }
</script>

</html>
